<!doctype html>
<html>
 <head>
  <meta charset="UTF-8">
  <title>markup</title>
  <link rel="stylesheet" href="./markup.css" />
  <!--
  <link rel="stylesheet" href="highlight.min.css">
  <script src="highlight.min.js"></script>
  -->
  <style type="text/css">
	body{display: grid;grid-template-columns: 50% .5rem 1fr;margin:0;padding:0;}

	.raw{overflow:auto;height:100vh;margin:0;padding:1rem .5rem;line-height: 1.5rem;/* text-wrap: balance; */font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;}
	.result{overflow:auto;height:100vh;margin:0;padding:0 .5rem; }
	.delimiter{background-color:rgba(0, 0, 0, 0.05);cursor: col-resize;position:relative;display: flex;justify-content: center;align-items: center;user-select: none;}
  </style>
 </head>
 <body>
  <pre class="raw" contentEditable="true">
	[1][c markup 简介][#top]
	----

	[2] 1 简介
	[3] 1.1 简介
	markdown功能少了点，而且不太喜欢它的语法，所以重新设计了一套。

	[3] 1.2 使用
	```javascript
	//npm install @wizardchen/markup

	import Markup from '@wizardchen/markup'
	import {readFileSync} from 'node:fs';
	let content = readFileSync('README.mup', {encoding:'utf-8'});
	new Markup({content}).print((content) => console.info(content));
	```
	或者
	```html
	&lt;script src="markup.umd.cjs" type="text/javascript">&lt;/script>
	&lt;script type="text/javascript">
	new Markup({content:document.querySelector('pre').textContent}).print(document.body);
	&lt;/script>
	```

	[2] 2 语法

	[3] 2.1 标题
	使用`[n]文字`或者`[n 文字]`来表示标题，从大到小共有6级，如
	[.section 
		[1]一级标题
		[4 四级标题]
		[6 六级标题]
		[7 超过6级也不会错，但没什么效果]
	]

	[3]2.2 字体
	使用`[b 文字]`来表示[b 粗体]
	使用`[i 文字]`来表示[i 斜体]
	使用`[u 文字]`或者`[_ 文字]`来表示[_ 下划线]
	使用`[d 文字]`或者`[s 文字]`或者`[- 文字]`来表示[- 删除线]
	使用`[-1 文字]`或者`[-1]文字`来表示[-1 小一点的字体]，相当于0.9rem；`[-2 文字]`表示[-2 更小一点的字体]，相当于0.8rem，依此类推
	使用`[+1 文字]`或者`[+1]文字`来表示[+1 大一点的字体]，相当于1.1rem；`[+2 文字]`表示[+2 更大一点的字体]，相当于1.2rem，依此类推
	[c 使用`[c 文字]`来表示居中]
	---4
	[l 使用`[l 文字]`来表示左对齐[-3 （注：默认就是左对齐）]]
	---|4
	[r 使用`[r 文字]`来表示右对齐]
	---4|
	[-3 注：如上所示，[左、右、居中] 对齐请在整行文本中使用，否则会强制在单独一行中显示]

	[3]2.3 分隔线
	使用多于三个的横线`---`来表示分隔线，如
	---|75%

	[3]2.4 引用
	使用`[> 文字]`或者`> 文字`来表示引用，如
	> 

	> 从来如此，便对么？ --鲁迅
	> 人类的悲欢并不相通，我只觉得他们吵闹。 --鲁迅

	>>>> 鲁迅：我确实这么说过。
	[> 愿中国青年都摆脱冷气，只是向上走，不必听自暴自弃者流的话。能做事的做事，能发声的发声。有一分热，发一分光。就令萤火一般，也可以在黑暗里发一点光，不必等候炬火。
		[r --鲁迅--]
		[>> 鲁迅：有的人活着，他已经死了；有的人死了，他还活着。]
	]


	[3]2.5 列表
	使用`- 文字`[-3 （注：-后面须加空格）]或者`[ul]`来表示无序列表，例如
	----|50%
	- 列表1
	  - xxxx
	    - 1234
	    - 5678
	    oooo
	  - zzzz
	- 列表2
	- 列表3
	- 列表4
	----|50%
	[ul type="none"]
	列表1
		[ul]
		hello
		world
		  [ul]
		  1234
		xxxx
	  [ul]
	  xxx
	  zzz
	列表2
	列表3
	列表4

	----|50%
	使用`+ 文字`[-3 （注：+后面须加空格）]或者`[ol]`来表示有序列表
	----|50%
	+ 列表1
	  [ol]
	  一
	  二
	  三
	+ 列表2
	+ 列表3
	+ 列表4
	----|50%
	[ol type="cjk-decimal"]
	列表1
	列表2
	列表3
	列表4

	----|50%
	注：使用`[ul]`或者`[ol]`形式的列表，必须在最后添加一空行表示结束。
	另外，如上所示，如需要嵌套或者在列表项内添加其他内容，则在第二行前面加两个空格即可。

	[3]2.6 代码
	使用`\`\``或者`[\` code]`来表示代码，比如`code`、[` code]

	[3]2.7 代码块
	代码块有两种形式，符号都需要成对出现
	1、三个点号`\`\`\``包起来的文字，如
	```java
	// FileName: HelloWorld.java
	public class HelloWorld {
		// Java 入口程序，程序从此入口
		public static void main(String[] args) {
			System.out.println("Hello,World!"); // 向控制台打印一条语句
		}
	}
	```
	2、使用`[\`]`包起来的文字，如
	[`javascript]
	class HelloWorld{
		constructor(){
			console.info('hello world.');
		}
	}
	new HelloWorld();
	[`]

	[3]2.8 链接
	使用`[link name* address]`来表示链接，如
	- [link klwxs http://www.klwxs.com]
	- [link 返回顶端 #top]
	- [link http://www.klwxs.com]
	- [link wizardChen@foxmail.com]

	[3]2.9 图片
	使用`[image|img|pic name* address wxh*]`来表示图片，如
	[image 图片 ./assets/pic.png 4x4]	[img 图片 assets/pic.png x8]	[pic ]
	[-3 注：图片的尺寸单位默认使用em（即多少个字符宽度）而不是px]

	[3]2.10 表格
	使用`[table]content`或者`[table content]`来表示表格，单元格之间使用任意多个空格或者制表符`\\t`隔开。
	第一种方式：注意这种方式需要在最后使用空行表示结束。[-3 （注：必须空一行结束）]
	[table]
	标题		|标题2			标题3|
	内容xxxx1	内容2，超长长长		1
	|左对齐		右对齐|			2
	|居中|		右对齐			内容3

	第二种方式：
	[table thead="false"
		指定thead="false"	可以去掉标题		这就是
		指定split="regexp"	可以自定义分隔符	~
	]
	样式默认居中对齐，如想左对齐，在内容左侧加竖线即可（`|文字`），右对齐则加在右侧（`文字|`），居中则加在两侧（`|文字|`）。
	单独一个波浪线`~`表示将当前单元格合并到左边，单独一个`^`符号表示将当前单元格合并到上一行。
	[c 
		[table split="\s*\|\s+"]
		|标题         | 标题 | ~    |
		|内容         | 内容 | 内容 |
		|[c [b 总结]] |   ~  | 0    |
		|^                   | 1    |
	]

	[3]2.11 脚注
	使用`[^label]`来表示引用式脚注，或者使用`[^ text]`来表示行内脚注[-3 （注意^符号后面的空格）]。
	引用式脚注可以使用`[^*]`来表示自动增长的数字编码，另外需要在文档的其他地方（一般是结尾）使用`[^ 换行 label:text]`的方式说明，如
	```none
	[^
		label:text
		*:自动数字编码的脚注，从1开始，依次递增
	]
	```
	示例：
	这是一个脚注[^*]
	这是另一个脚注[^*]
	这也是一个脚注[^RFC文档目录]
	这是行内脚注[^ [link RFC 7540 - HTTP/2 中文翻译版 https://github.com/abbshr/rfc7540-translation-zh_cn]]
	[^
		RFC文档目录：https://docs.huihoo.com/rfc/
		*:自增长1
		*:自增长2
	]

	[3]2.12 引用
	使用`[& label]`来表示一个引用，引用的内容可以在稍后定义，显示时将使用定义的内容替代。
	使用`[& 换行 label:text]`来定义简单的引用内容；
	使用`[&label text]`来定义单独的引用内容。
	示例：
	这里有两个网站：[& klwxs] 和 [& surge]
	这里有个表格
	[& 表格]
	图片也可以[& pic]
	引用内容可以最后在文本末尾定义，也可以在任何其他地方定义，它并不会显示到最终文档中。
	[&
		klwxs:[link 站点一 http://www.klwxs.com]
		surge:[link 站点二 http://www.surge.sh]
		pic:[pic chrome ./assets/pic.png x8]
	]
	[&表格
		[table]
		日期              收入        支出         余额
		2024年12月20日    100.00|     200.00|     -100.00|
		^                  50.00       23.00       -73.00
		^                 123.00       88.00       -38.00
		|合计|            273.00      311.00       -38.00
	]

	[2]3 其他

	[3] 3.1 转义符
	使用斜线`\\`作为转义符，如两个斜线`\\\\`表示一个斜线`\\`，`\\[b xxx]`将显示文本\[b xxx]

	[3] 3.2 类
	使用`[.className 文字]`或者`[.className]文字`来给文字添加css class，如
	[.red 红色]
	[.green.under-line]绿色下划线

	[3] 3.3 样式
	使用`[style]`定义css样式。[-3 （注：末尾需要空一行以示结束）]如
	[.custyle [.red 自定义样式]]
	[style scope=".custyle"]
	.red{color:gray}

	[style]
	h2{text-decoration: underline;}
	.wrap, .wrap.section{ padding-left:2em; }
	.wrap:has(h1,h2,h3,h4,h5,h6){ padding-left:0; }
	.odd-even .table tr:nth-child(2n) { background-color: #f6f8fa; }

	[-2 开发者可以在初始化时通过指定`opts.allowStyle=false`来禁用此项功能，还可以指定`opts.allowStyle={scope:'xxx'}`来指定所有样式的作用域范围，但是请注意，不是所有浏览器都支持。]
	[3] 3.4 html
	支持html标签。
	[-2 开发者可以在初始化时使用`opts.htmlWhiteList`或者`opts.htmlBlackList`参数来过滤html标签，默认使用`opts.htmlBlackList=['script', 'iframe', 'form', 'object', 'embed', 'style']`]

	[3] 3.5 速查表
	[.odd-even 
		[table CRLF=" \| "]
		元素                        语法
		标题（Heading）             `[1-6]`
		粗体（Bold）                `[b]text`、`[b text]`
		斜体（Italic）              `[i]text`、`[i text]`
		下划线（Underline）         `[_]text`、`[_ text]`、`[u text]`、`[u]text`
		删除线（Strikethrough）     `[-]text`、`[- text]`、`[d text]`、`[s]text`
		对齐（Align）               `[c]text`、`[c text]`、`[l text]`、`[r]text`
		字体大小（Font Size）       `[±1]text`、`[±1 text]`
		引用块（Blockquote）        `> text`、`[> text]`
		有序列表（Ordered List）    `+ text`、`[ol]`
		无序列表（Unordered List）  `- text`、`[ul]`
		代码（Code）                `\`code\``、`[\` code]`
		代码块（Code Block）        `\`\`\`code\`\`\``、`[\`]code[\`]`
		分隔线（Horizontal Rule）   `---`
		链接（Link）                `[link name* address]`
		图片（Image）               `[image|img|pic name* address wxh*]`
		表格（Table）               `[table]` | [-3 单元格之间使用两个以上空格隔开] | [-3 最后空一行结束]
		^                           `[table` | [-3 单元格之间使用两个以上空格隔开] | `]`
		脚注（Footnote）            [-3 引用式脚注：]`[^*]`、`[^label]`
		^                           [-3 行内式脚注：]`[^ text]`[-3 注意^后面有空格]
		^                           [-3 脚注注脚：]`[^ | label:text | *:text | ]`
		引用（Reference）           [-3 标记引用：]`[& label]`
		^                           [-3 简单定义：]`[& | label:text | label:text | ]`
		^                           [-3 单独定义：]`[&label | text | ]`
		类（Class）                 `[.className]text`、`[.className text]`
		ID（ID）                    `[#ID]`、`[#ID text]`
		样式（Style）               `[style] | style code` | [-3 空一行结束]
	]
  </pre>
  <div class="delimiter">||</div>
  <div class="result"></div>

  <script type="module">
	import Markup from './index.js';

	let $raw = document.querySelector('.raw');
		$raw.innerHTML = $raw.innerHTML.replace(/^\t/mg, '');

	let str = $raw.textContent;
	//console.info($raw.textContent);

	let $res = document.querySelector('.result');


	let highlight = {
		loadScript({name, src, onload}){
			if( name ){
				let script = document.querySelector(`script[name="${name}"]`);
				if( script ){
					return false;
				}
			}
			let script = document.createElement('script');
				script.type = 'text/javascript';
				script.src = src;
				script.name = name;
				script.onload = onload;
			(document.head || document.getElementsByTagName('head')[0]).appendChild(script);
		},
		loadCss({name, src, onload}){
			if( name ){
				let link = document.querySelector(`link[name="${name}"]`);
				if( link ){
					return false;
				}
			}
			let link = document.createElement('link');
				link.rel = 'stylesheet';
				link.name = name;
				link.href = src;
				link.onload = onload;
			(document.head || document.getElementsByTagName('head')[0]).appendChild(link);
		},
		render(){
			let render = () => {
				let func = () => {
					if( window.hasOwnProperty('hljs') ){
						let $dom = document.querySelectorAll('.code-text code:not(.none)')
						if( $dom.length ){
							$dom = Array.from($dom).filter($dom => !$dom.classList.contains('hljs'));
							if( $dom.length ){
								$dom.forEach($code => {
									hljs.highlightElement($code);
								});
								return true;
							}
							return false;
						}
						setTimeout(func, 500);
					}
				}
				func();
			}
			if( !window.hasOwnProperty('hljs') ){
				let js = './assets/highlight.min.js';
				let css = './assets/highlight.min.css';
				////cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css
				////cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js
				this.loadScript({name: 'highlight', src: js, onload:render});
				this.loadCss({name: 'highlight', src: css});
			}
			render();
		},
	}

	let markup = () => {
		let markup = new Markup({
			content : $raw.textContent,
			opts : {
				highlight: ()=>highlight.render(),
			}
		}).print($res);
		console.info(markup.segment);
	}
	markup();

	let insertText = (text) => {
		let selection = window.getSelection();
		for(let i=0; i<selection.rangeCount; i++){
			let range = selection.getRangeAt(i);
				range.deleteContents();
				range.insertNode(new Text(text));
				range.collapse();
		}
	}
	$raw.addEventListener('keydown', (event) => {
		let key = event.which || event.keyCode;
		if( key == 13 ){
			insertText('\n');
			event.preventDefault();
		}
	});
	$raw.addEventListener('input', (event) => {
		markup();
	});
	$raw.addEventListener('paste', (event) => {
		const clipboardData = event.clipboardData || window.clipboardData;
		const text = clipboardData.getData('text');
		if( text ){
			insertText(text);
			event.preventDefault();
			markup();
		}
	});


	let delimiter = {
		$el : document.querySelector('.delimiter'),
		$target : document.body,
		pos : {x:0},
		gtcs : [],
		onInit({x}){
			if( !this.gtcs.length ){
				Object.assign(this.pos, {x});
				this.gtcs = window.getComputedStyle(this.$target).gridTemplateColumns.replace(/px/g, '').split(/\s/).map(n => parseInt(n));
			}
		},
		onMove({x}){
			if( this.gtcs[0] && this.gtcs[2] ){
				this.$shadow.style.left = x - this.pos.x + 'px';
			}
		},
		onDone({x}){
			if( this.gtcs[0] && this.gtcs[2] ){
				let distance = x - this.pos.x;
				this.gtcs[0] = this.gtcs[0] + distance;
				this.gtcs[2] = this.gtcs[2] - distance;
				this.$target.style.gridTemplateColumns = this.gtcs.map(n => n + 'px').join(' ');
				this.$shadow.style.left = 0;
			}
			this.gtcs = [];
		},
		init(){
			let $el = this.$el;
				$el.addEventListener('mousedown', (event) => {
					this.onInit({x:event.pageX, y:event.pageY});
				});
				document.addEventListener('mousemove', (event) => {
					if( this.gtcs.length ){
						this.onMove({x:event.pageX, y:event.pageY});
					}
				});
				document.addEventListener('mouseup', (event) => {
					this.onDone({x:event.pageX, y:event.pageY});
				});
			
			this.$shadow = this.$el.cloneNode();
			this.$shadow.className = 'shadow';
			this.$shadow.style = `
				position:absolute;
				width:100%;
				height:100%;
				background-color:rgba(0, 0, 0, 0.05);
			`;
			this.$el.appendChild(this.$shadow);
		}
	}
	delimiter.init();
  </script>
 </body>
</html>
